<!DOCTYPE html><html lang="[&quot;zh-Hans&quot;,&quot;zh-CN&quot;,&quot;default&quot;]"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><meta name="description" content="electron+react+七牛云开发笔记"><meta name="keywords" content="electron,React"><meta name="author" content="wenmu"><meta name="copyright" content="wenmu"><title>electron+react+七牛云开发笔记 | 温木的博客</title><link rel="shortcut icon" href="/melody-favicon.ico"><link rel="stylesheet" href="/css/index.css?version=1.6.1"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@latest/css/font-awesome.min.css?version=1.6.1"><link rel="dns-prefetch" href="https://cdn.staticfile.org"><link rel="dns-prefetch" href="https://cdn.bootcss.com"><link rel="dns-prefetch" href="https://creativecommons.org"><link rel="dns-prefetch" href="http://ta.qq.com"><script>(function() {
   var hm = document.createElement("script");
   hm.src = "https://tajs.qq.com/stats?sId=&lt;script type=&quot;text/javascript&quot; src=&quot;http://tajs.qq.com/stats?sId=66523541&quot; charset=&quot;UTF-8&quot;&gt;&lt;/script&gt;";
   var s = document.getElementsByTagName("script")[0];
   s.parentNode.insertBefore(hm, s);
 })();</script><script>var GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: undefined,
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  }
} </script><meta name="generator" content="Hexo 4.2.0"></head><body><i class="fa fa-arrow-right" id="toggle-sidebar" aria-hidden="true"></i><div id="sidebar"><div class="toggle-sidebar-info text-center"><span data-toggle="切换文章详情">切换站点概览</span><hr></div><div class="sidebar-toc"><div class="sidebar-toc__title">目录</div><div class="sidebar-toc__progress"><span class="progress-notice">你已经读了</span><span class="progress-num">0</span><span class="progress-percentage">%</span><div class="sidebar-toc__progress-bar"></div></div><div class="sidebar-toc__content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#Electron-和-React-双剑合璧做-markdown"><span class="toc-number">1.</span> <span class="toc-text">Electron 和 React 双剑合璧做 markdown</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#环境准备"><span class="toc-number">1.1.</span> <span class="toc-text">环境准备</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#优化启动命令"><span class="toc-number">1.2.</span> <span class="toc-text">优化启动命令</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#一个命令窗口启动项目"><span class="toc-number">1.2.1.</span> <span class="toc-text">一个命令窗口启动项目</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#当-react-启动后再启动-electron"><span class="toc-number">1.2.2.</span> <span class="toc-text">当 react 启动后再启动 electron</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#禁止-react-自动打开浏览器"><span class="toc-number">1.2.3.</span> <span class="toc-text">禁止 react 自动打开浏览器</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#react-markdown-编辑器"><span class="toc-number">1.3.</span> <span class="toc-text">react-markdown 编辑器</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#设置-key"><span class="toc-number">1.3.1.</span> <span class="toc-text">设置 key</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#扁平化处理"><span class="toc-number">1.3.2.</span> <span class="toc-text">扁平化处理</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#检测-electron-是否是开发环境"><span class="toc-number">1.4.</span> <span class="toc-text">检测 electron 是否是开发环境</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#在-react-中使用-Node-js-的-API"><span class="toc-number">1.5.</span> <span class="toc-text">在 react 中使用 Node.js 的 API</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#require-的小-bug"><span class="toc-number">1.5.1.</span> <span class="toc-text">require 的小 bug</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#查看-electron-的-node-版本"><span class="toc-number">1.5.2.</span> <span class="toc-text">查看 electron 的 node 版本</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#数据持久化"><span class="toc-number">1.6.</span> <span class="toc-text">数据持久化</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#菜单功能"><span class="toc-number">1.7.</span> <span class="toc-text">菜单功能</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#实现上线文菜单功能"><span class="toc-number">1.7.1.</span> <span class="toc-text">实现上线文菜单功能</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#获取菜单的数据"><span class="toc-number">1.7.2.</span> <span class="toc-text">获取菜单的数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#判断元素是否用了某个样式-class"><span class="toc-number">1.7.3.</span> <span class="toc-text">判断元素是否用了某个样式 class</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#menu-的事件"><span class="toc-number">1.8.</span> <span class="toc-text">menu 的事件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#应用程序打包"><span class="toc-number">1.9.</span> <span class="toc-text">应用程序打包</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#asar-的优点"><span class="toc-number">1.9.1.</span> <span class="toc-text">asar 的优点</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#打包-View-层的代码"><span class="toc-number">1.9.2.</span> <span class="toc-text">打包 View 层的代码</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#electron-builder"><span class="toc-number">1.9.3.</span> <span class="toc-text">electron-builder</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#自定义需要打包的文件"><span class="toc-number">1.9.4.</span> <span class="toc-text">自定义需要打包的文件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#设置路径"><span class="toc-number">1.9.5.</span> <span class="toc-text">设置路径</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#打包"><span class="toc-number">1.9.6.</span> <span class="toc-text">打包</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#查看安装包内容"><span class="toc-number">1.10.</span> <span class="toc-text">查看安装包内容</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#生成安装包"><span class="toc-number">1.11.</span> <span class="toc-text">生成安装包</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#优化安装包"><span class="toc-number">1.12.</span> <span class="toc-text">优化安装包</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#electron-代码打包到一起后需要修改的地方"><span class="toc-number">1.12.1.</span> <span class="toc-text">electron 代码打包到一起后需要修改的地方</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#自动更新"><span class="toc-number">1.13.</span> <span class="toc-text">自动更新</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#自动发布"><span class="toc-number">1.13.1.</span> <span class="toc-text">自动发布</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#自动更新-1"><span class="toc-number">1.13.2.</span> <span class="toc-text">自动更新</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#开发模式下测试自动更新"><span class="toc-number">1.13.3.</span> <span class="toc-text">开发模式下测试自动更新</span></a></li></ol></li></ol></li></ol></div></div><div class="author-info hide"><div class="author-info__avatar text-center"><img src="https://i.loli.net/2020/02/27/xwaBoOj158MfNyq.jpg"></div><div class="author-info__name text-center">wenmu</div><div class="author-info__description text-center">记录一些在工作中或学习新知识时学到的一些知识点；正所谓好记性不如一个烂笔头，温故而知新！</div><hr><div class="author-info-articles"><a class="author-info-articles__archives article-meta" href="/archives"><span class="pull-left">文章</span><span class="pull-right">115</span></a><a class="author-info-articles__tags article-meta" href="/tags"><span class="pull-left">标签</span><span class="pull-right">52</span></a><a class="author-info-articles__categories article-meta" href="/categories"><span class="pull-left">分类</span><span class="pull-right">30</span></a></div></div></div><div id="content-outer"><div class="no-bg" id="top-container"><div id="page-header"><span class="pull-left"> <a id="site-name" href="/">温木的博客</a></span><i class="fa fa-bars toggle-menu pull-right" aria-hidden="true"></i><span class="pull-right menus"><a class="site-page" href="/">首页</a><a class="site-page" href="/archives">文章</a><a class="site-page" href="/tags">标签</a><a class="site-page" href="/categories">分类</a></span></div><div id="post-info"><div id="post-title">electron+react+七牛云开发笔记</div><div id="post-meta"><time class="post-meta__date"><i class="fa fa-calendar" aria-hidden="true"></i> 2020-01-09</time><span class="post-meta__separator">|</span><i class="fa fa-inbox post-meta__icon" aria-hidden="true"></i><a class="post-meta__categories" href="/categories/electron/">electron</a></div></div></div><div class="layout" id="content-inner"><article id="post"><div class="article-container" id="post-content"><h1 id="Electron-和-React-双剑合璧做-markdown"><a href="#Electron-和-React-双剑合璧做-markdown" class="headerlink" title="Electron 和 React 双剑合璧做 markdown"></a>Electron 和 React 双剑合璧做 markdown</h1><p>使用 Electrong 、 React 和七牛云做一个在线 markdown。</p>
<a id="more"></a>

<h2 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h2><p>使用<code>creact-react-app</code>创建 react，然后在里面添加 electron 的代码和配置即可。<br>react 和 electron 结合，需要启动两个服务，在 electron 的窗口中嵌入 react 启动的页面。</p>
<h2 id="优化启动命令"><a href="#优化启动命令" class="headerlink" title="优化启动命令"></a>优化启动命令</h2><ol>
<li>一个命令窗口启动项目</li>
<li>当 react 启动后再启动 electron</li>
<li>关闭 create-react-app 启动时自动打开浏览器的功能</li>
</ol>
<h3 id="一个命令窗口启动项目"><a href="#一个命令窗口启动项目" class="headerlink" title="一个命令窗口启动项目"></a>一个命令窗口启动项目</h3><p>因为 electron 和 react 需要分别启动，所以每次打开两个命令窗口比较麻烦，可以使用<code>Concurrently</code>插件的来实现这个功能。<br>Concurrently 的优点</p>
<ol>
<li>跨平台(window 和 mac 对 npm 原生的多命令同时运行符号&amp;支持不同)</li>
<li>控制台输出信息友好</li>
<li>一键停止启动的所有命令</li>
</ol>
<h3 id="当-react-启动后再启动-electron"><a href="#当-react-启动后再启动-electron" class="headerlink" title="当 react 启动后再启动 electron"></a>当 react 启动后再启动 electron</h3><p>上面配置完后，一个命令就把 electron 和 react 都启动了，由于是并行的，所以当 electron 启动时会先显示一个白屏，然后等 react 也启动了需要手动刷新一下，react 的页面才会显示出来。我们可以设置让 react 的服务启动后再启动 electron，这个可以使用 wait-on 插件</p>
<h3 id="禁止-react-自动打开浏览器"><a href="#禁止-react-自动打开浏览器" class="headerlink" title="禁止 react 自动打开浏览器"></a>禁止 react 自动打开浏览器</h3><p>这个是 webpac 的功能，设置自动开发浏览器的选项为 false 即可。这个<code>create-react-app</code>已经帮我们做了处理，只需设置环境变量即可。考虑到跨平台，使用<code>cross-env</code>设置环境变量。</p>
<h2 id="react-markdown-编辑器"><a href="#react-markdown-编辑器" class="headerlink" title="react-markdown 编辑器"></a>react-markdown 编辑器</h2><p>编辑器地址<a href="https://github.com/RIP21/react-simplemde-editor" target="_blank" rel="noopener">https://github.com/RIP21/react-simplemde-editor</a></p>
<h3 id="设置-key"><a href="#设置-key" class="headerlink" title="设置 key"></a>设置 key</h3><p>在给编辑器赋值时，如果编辑器的值是根据不同条件显示不同的内容，这时需要设置一个 key，不然即使条件发生变化，页面重新渲染，编辑器也无法读取到新的值。</p>
<h3 id="扁平化处理"><a href="#扁平化处理" class="headerlink" title="扁平化处理"></a>扁平化处理</h3><p>由于数组在操作时，操作某个元素都需要遍历查找，所以把数组扁平化处理，操作起来更方便。</p>
<h2 id="检测-electron-是否是开发环境"><a href="#检测-electron-是否是开发环境" class="headerlink" title="检测 electron 是否是开发环境"></a>检测 electron 是否是开发环境</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm install electron-is-dev</span><br><span class="line"></span><br><span class="line">const isDev = require(<span class="string">'electron-is-dev'</span>);</span><br></pre></td></tr></table></figure>

<h2 id="在-react-中使用-Node-js-的-API"><a href="#在-react-中使用-Node-js-的-API" class="headerlink" title="在 react 中使用 Node.js 的 API"></a>在 react 中使用 Node.js 的 API</h2><p>前面说过，在 electron 的渲染进程中的 js 不仅可以使用前端的各种 API， 我们还可以使用 Node 的 API。</p>
<blockquote>
<p>main.js 中启动 electron，并且创建窗口就是运行在主进程中，创建的各个窗口就是渲染进程，窗口中页面引用的 js 就是运行在渲染进程中的 js。</p>
</blockquote>
<p>因此我们可以在页面的 js 中直接使用 node 的 api 对本地系统资源进行操作。</p>
<h3 id="require-的小-bug"><a href="#require-的小-bug" class="headerlink" title="require 的小 bug"></a>require 的小 bug</h3><p>在网页的<code>js</code>中使用<code>require</code>关键字引入<code>node</code>的<code>api</code>，发现获取到的对象是空对象，在<code>electron</code>的<code>issues</code>中知道解决方法，把<code>require</code>改成<code>window.require</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// const fs = require('fs')  // 获取不到对象</span></span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">window</span>.require(<span class="string">"fs"</span>);</span><br></pre></td></tr></table></figure>

<p>原因：</p>
<blockquote>
<p>原来在写 demo 时没遇到这个问题，为什么现在遇到了呢？<br>因为原来写 demo 比较简单，使用最原始的方式写，运行是没问题的。但是现在的环境是使用了 react，因为我们的 react 使用了 webpack 进行了打包，webpack 会对 es6 的 import 和 require 都进行处理，webapck 对引入文件的寻找有自己的路径方式，所以当我们使用 require 的方式引入 fs 时，被 webpack 编译截胡了，所以就找不到对象了，前面加上 window,webpack 知道是原生的对象，就不做处理了。</p>
</blockquote>
<h3 id="查看-electron-的-node-版本"><a href="#查看-electron-的-node-版本" class="headerlink" title="查看 electron 的 node 版本"></a>查看 electron 的 node 版本</h3><p>这里要用到 promise 版本的 fs，但是这个是 node 10 版本后推出的，所以要确保 node 的版本是 10 之后，但是这里说的 node 版本不是本地安装的版本，而是 electron 中使用的版本。<br>如何查看 electron 的版本呢？<br>这个在 electron 给的 demo 中已经显示了各个工具的版本号，在页面的 js 中调用环境变量查看</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">process.versions.node;</span><br></pre></td></tr></table></figure>

<h2 id="数据持久化"><a href="#数据持久化" class="headerlink" title="数据持久化"></a>数据持久化</h2><p>node 提供了操作本地文件的功能，我们可以使用 node 提供的 api 把内容写入到本地系统的文件中。<br>electron 的主进程提供的<code>app.getPath(name)</code>方法可以方便获取本地一些目录路径，具体参考官网文档介绍。<br>我们把文件写入到这些路径中。</p>
<p>网页数据持久化<br>文档的的内容我们通过 node api 把文件写入到了本地磁盘上，网页上的数据列表我们也需要持久化，以避免刷新一下网页数据就没了;<br>我们插件<code>electron-store</code>，其实这个插件也是把数据存储在本地磁盘，数据存储在一个 json 文件中。</p>
<p>electron-store 的数据存储路径是通过<code>app.getPath(&#39;userData&#39;)</code>获取的，根据 electron 官网，mac 对应的是<code>~/Library/Application Support</code>文件夹中。<br>进入上面的文件夹，会看到一个和你项目同名的文件夹，<code>electron-store</code>的数据就存储在这个文件夹中。文件默认名字叫<code>config</code>，可以根据参数<code>name</code>来更改。</p>
<blockquote>
<p>mac 系统，在终端中进入包含空格的文件夹的方式</p>
<ol>
<li>使用*代替空格</li>
<li>使用反斜杠转义空格</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd Application\ Support</span><br><span class="line">cd Application*Support</span><br></pre></td></tr></table></figure>
</blockquote>
<h2 id="菜单功能"><a href="#菜单功能" class="headerlink" title="菜单功能"></a>菜单功能</h2><p>菜单也是主进程提供的 api，根据 electron 提供的 Menu 和 MenuItem 来创建菜单。</p>
<h3 id="实现上线文菜单功能"><a href="#实现上线文菜单功能" class="headerlink" title="实现上线文菜单功能"></a>实现上线文菜单功能</h3><p>所谓上下文菜单，主要是右键菜单。当点击右键时，触发上下文菜单事件<code>contextmenu</code>事件，然后把通过 Menu 创建的菜单实例传递给要显示的窗口。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> menu = <span class="keyword">new</span> Menu();</span><br><span class="line">menuItems.forEach(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">  menu.append(<span class="keyword">new</span> MenuItem(item));</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> onOpenContextMenu = <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// 判断点击的元素是否在指定的元素范围内</span></span><br><span class="line">  <span class="keyword">if</span> (<span class="built_in">document</span>.querySelector(targetSelctor).contains(e.target)) &#123;</span><br><span class="line">    clickedElemnt.current = e.target;</span><br><span class="line">    <span class="comment">// 指定菜单在哪个窗口中显示</span></span><br><span class="line">    menu.popup(&#123; <span class="attr">window</span>: remote.getCurrentWindow &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">// 打开上下文菜单时触发</span></span><br><span class="line"><span class="built_in">window</span>.addEventListener(<span class="string">"contextmenu"</span>, onOpenContextMenu);</span><br></pre></td></tr></table></figure>

<h3 id="获取菜单的数据"><a href="#获取菜单的数据" class="headerlink" title="获取菜单的数据"></a>获取菜单的数据</h3><p>在点击菜单时，可以根据点击的元素来获取元素的属性，比如 id，但是我们可能需要更多的信息，我们可以自定义一些属性，然后通过节点的属性获取；这是老方法，html5 提供了更方便更规范的方法，即设置<code>data-*</code>属性，通过这种方式设置的属性，可以通过<code>HTMLElement.dataset</code>来获取他们。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;div id=<span class="string">"user"</span> data-id=<span class="string">"1234567890"</span> data-user=<span class="string">"johndoe"</span> data-date-<span class="keyword">of</span>-birth&gt;</span><br><span class="line">  John Doe</span><br><span class="line">&lt;<span class="regexp">/div&gt;;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">var el = document.querySelector("#user");</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ el.id ===&gt; 'user'</span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ el.dataset.id ===&gt; '1234567890'</span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ el.dataset.user ===&gt; 'johndoe'</span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ el.dataset.dateOfBirth ===&gt; ''</span></span><br></pre></td></tr></table></figure>

<h3 id="判断元素是否用了某个样式-class"><a href="#判断元素是否用了某个样式-class" class="headerlink" title="判断元素是否用了某个样式 class"></a>判断元素是否用了某个样式 class</h3><p>以前用 jquery，可以很方便做各种操作，其实现在原生的也提供了很多方便的 api。<br>元素的 classList 就是元素所有的样式类，并且提供了多种操作方法，判断是否包含某一个，可以简单实现</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">node.classList.contains(<span class="string">"classname"</span>); <span class="comment">// true | false</span></span><br></pre></td></tr></table></figure>

<h2 id="menu-的事件"><a href="#menu-的事件" class="headerlink" title="menu 的事件"></a>menu 的事件</h2><p>menu 触发的事件是在主进程中触发的，所以 menu 事件需要通过进程之间的通信方式来通信。<br>同一进程之间的通信使用 ipcMain 来进行，</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 触发</span></span><br><span class="line">ipcMain.emit(<span class="string">"事件名"</span>);</span><br><span class="line"><span class="comment">// 监听</span></span><br><span class="line">ipcMain.on(<span class="string">"事件名"</span>, () =&gt; &#123;&#125;);</span><br></pre></td></tr></table></figure>

<p>在<code>menuTemplate</code>中的 menu 事件都发送到了 main 中进行处理，其实可以直接处理，然后把结果返回给渲染进程。这里是为了统一。</p>
<p>主进程和渲染进程之间的通信是通过 主窗口的实例(mainWindow) 和 ipcRender，在主进程中使用 mainWindow.webContents.send()，在渲染进程中使用 ipcRender；<br>在渲染进程中，即在页面中可以直接使用 node 的 api 进行业务处理。</p>
<h2 id="应用程序打包"><a href="#应用程序打包" class="headerlink" title="应用程序打包"></a>应用程序打包</h2><p>为缓解 Windows 下路径名过长的<a href="https://github.com/nodejs/node-v0.x-archive/issues/6960" target="_blank" rel="noopener">问题</a>， 略微加快一下 <code>require</code> 的速度以及<strong>隐藏你的源代码</strong>，你可以选择把你的应用打包成 <code>asar</code> 档案文件，这只需要对你的源代码做一些很小的改动。<br>大部分用户可以毫不费力地使用这个功能，因为它在 electron-packager,、electron-forge 和 electron-builder 中都得到了支持，开箱即用。</p>
<h3 id="asar-的优点"><a href="#asar-的优点" class="headerlink" title="asar 的优点"></a>asar 的优点</h3><ol>
<li>缓解 Windows 下路径名过长的问题</li>
<li>略微加快 require 的速度</li>
<li>隐藏源代码</li>
</ol>
<h3 id="打包-View-层的代码"><a href="#打包-View-层的代码" class="headerlink" title="打包 View 层的代码"></a>打包 View 层的代码</h3><p>因为项目里面使用的 react，不能在浏览器中直接使用，所以需要使用 webpack 打包成浏览器能识别的静态资源，这和常规打包没什么区别，直接使用<code>create-react-app</code>提供的 build 命令即可。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build</span><br></pre></td></tr></table></figure>

<p>设置加载路径，把 electron 的加载页面路径设置成打包后文件的路径</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> urlLocation = isDev</span><br><span class="line">  ? <span class="string">"http://localhost:3000/"</span></span><br><span class="line">  : <span class="string">`file://<span class="subst">$&#123;path.join(__dirname, <span class="string">"./build/index.html"</span>)&#125;</span>`</span>;</span><br></pre></td></tr></table></figure>

<h3 id="electron-builder"><a href="#electron-builder" class="headerlink" title="electron-builder"></a>electron-builder</h3><p>我们使用 electron-builder 来打包。</p>
<ol>
<li><p>配置<br>electrong-builder 的配置比价简单，直接在 package.json 中进行配置。<br>在根节点增加<code>build</code>项，在里面写相关的配置</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"build"</span>: &#123;</span><br><span class="line"> <span class="string">"appId"</span>: <span class="string">"electron-react-markdown"</span>,</span><br><span class="line"> <span class="string">"productName"</span>: <span class="string">"七牛云文档管理"</span>,</span><br><span class="line"> <span class="string">"copyright"</span>: <span class="string">"Copyright @ 2019-12 $&#123;author&#125;"</span>,</span><br><span class="line"> <span class="comment">// 这个默认设置了入口文件的名字，关闭会用我们自己的入口文件</span></span><br><span class="line"> <span class="string">"extends"</span>: <span class="literal">null</span>,</span><br><span class="line"> <span class="comment">// 如果不同平台需要单独配置相关参数，可以增加相关的配置，比如下面是mac系统的配置</span></span><br><span class="line"> <span class="string">"mac"</span>: &#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>增加 build 命令</p>
</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"scripts"</span>: &#123;</span><br><span class="line">  ......</span><br><span class="line">  <span class="string">"pack"</span>: <span class="string">"electron-builder --dir"</span>,</span><br><span class="line">  <span class="string">"dist"</span>: <span class="string">"electron-builder"</span></span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>

<p>pack 和 dist 的区别<br>pack 生成的是安装包安装后生成的那些文件。<br>dist 生成安装包</p>
<p>增加钩子<br>我们可以在执行命令的时候，指定先执行哪个命令，这个是 npm 提供的钩子；<br>方式是把相关命令的前面加上<code>pre</code>即可，比如下面是执行 pack 的时候，先执行 build</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"pack"</span>: <span class="string">"electron-builder --dir"</span>,</span><br><span class="line"><span class="string">"prepack"</span>:<span class="string">"npm run build"</span></span><br></pre></td></tr></table></figure>

<h3 id="自定义需要打包的文件"><a href="#自定义需要打包的文件" class="headerlink" title="自定义需要打包的文件"></a>自定义需要打包的文件</h3><p>build 的 files 字段配置了打包时，哪些文件会被打包到程序中。它有自己的默认配置，但是一旦自定义了这个字段，默认的就不起作用了。<br>这里需要指定的文件是在 electron 进程中用到的文件，react 中用到的都已打包到 build 目录中，只需指定 build 目录即可。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">"build":&#123;</span><br><span class="line">    "files": [</span><br><span class="line">      "build/**/*",</span><br><span class="line">      "node_modules/**/*",</span><br><span class="line">      "settings/**/*",</span><br><span class="line">      "package.json",</span><br><span class="line">      "main.js",</span><br><span class="line">      "./menuTemplate.js",</span><br><span class="line">      "./src/AppWindow.js",</span><br><span class="line">      <span class="string">"./src/utils/QiNiuManager.js"</span></span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>files 的配置说明</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line">  <span class="comment">// match all files|| 匹配所有文件</span></span><br><span class="line">  <span class="string">"**/*"</span>,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// except for js files in the foo/ directory || 不匹配foo文件夹下js，其他文件仍能匹配</span></span><br><span class="line">  <span class="string">"!foo/*.js"</span>,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// unless it's foo/bar.js || 匹配foo/bar.js文件</span></span><br><span class="line">  <span class="string">"foo/bar.js"</span></span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<h3 id="设置路径"><a href="#设置路径" class="headerlink" title="设置路径"></a>设置路径</h3><p>在 package.json 中设置</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"homepage": "./",</span><br></pre></td></tr></table></figure>

<h3 id="打包"><a href="#打包" class="headerlink" title="打包"></a>打包</h3><p>通过上面的配置，现在执行打包命令，因为 pack 生成的就是安装后的文件，所以可以进入文件夹直接打开使用。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run pack</span><br></pre></td></tr></table></figure>

<h2 id="查看安装包内容"><a href="#查看安装包内容" class="headerlink" title="查看安装包内容"></a>查看安装包内容</h2><p>我用的是 mac 系统，点击生成的安装包，右键–查看包内容，可以看到一个 Contents 文件夹，文件中包含了所有的文件。</p>
<h2 id="生成安装包"><a href="#生成安装包" class="headerlink" title="生成安装包"></a>生成安装包</h2><p>配置如下：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line">"build": &#123;</span><br><span class="line">  "appId": "electron-react-markdown",</span><br><span class="line">  "productName": "七牛云文档管理",</span><br><span class="line">  "copyright": "Copyright @ 2019-12 $&#123;author&#125;",</span><br><span class="line">  "extends": null,</span><br><span class="line">  "files": [</span><br><span class="line">    "build/**/*",</span><br><span class="line">    "node_modules/**/*",</span><br><span class="line">    "settings/**/*",</span><br><span class="line">    "package.json",</span><br><span class="line">    "main.js",</span><br><span class="line">    "./menuTemplate.js",</span><br><span class="line">    "./src/AppWindow.js",</span><br><span class="line">    <span class="string">"./src/utils/QiNiuManager.js"</span></span><br><span class="line">  ],</span><br><span class="line">  "directories": &#123;</span><br><span class="line">    <span class="comment">// 指定静态资源的路径</span></span><br><span class="line">    "buildResources": "assets"</span><br><span class="line">  &#125;,</span><br><span class="line">  "mac": &#123;</span><br><span class="line">    <span class="comment">// mac电脑的应用程序有分类，这里指定安装到哪个分类下</span></span><br><span class="line">    "category": "public.app-category.productivity",</span><br><span class="line">    <span class="comment">// 打出的安装包的名字</span></span><br><span class="line">    "artifactName": "$&#123;productName&#125;-$&#123;version&#125;-$&#123;arch&#125;.$&#123;ext&#125;"</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  "dmg": &#123;</span><br><span class="line">    "background": "assets/appdmg.png",</span><br><span class="line">    "icon": "assets/icon.icns",</span><br><span class="line">    "iconSize": 100,</span><br><span class="line">    "contents": [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">"x"</span>: <span class="number">380</span>,</span><br><span class="line">        <span class="attr">"y"</span>: <span class="number">280</span>,</span><br><span class="line">        <span class="attr">"type"</span>: <span class="string">"link"</span>,</span><br><span class="line">        <span class="attr">"path"</span>: <span class="string">"/Applications"</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">"x"</span>: <span class="number">100</span>,</span><br><span class="line">        <span class="attr">"y"</span>: <span class="number">280</span>,</span><br><span class="line">        <span class="attr">"type"</span>: <span class="string">"file"</span></span><br><span class="line">      &#125;</span><br><span class="line">    ],</span><br><span class="line">    <span class="comment">// 打开的安装窗口大小</span></span><br><span class="line">    "window": &#123;</span><br><span class="line">      "width": 500,</span><br><span class="line">      "height": 500</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  "win": &#123;</span><br><span class="line">    <span class="comment">// 这里指定打包出两种类型的安装包</span></span><br><span class="line">    "target": [</span><br><span class="line">      "msi",</span><br><span class="line">      <span class="string">"nsis"</span></span><br><span class="line">    ],</span><br><span class="line">    "icon": "assets/icon.ico",</span><br><span class="line">    "artifactName": "$&#123;productName&#125;-Web-Setup-$&#123;version&#125;.$&#123;ext&#125;",</span><br><span class="line">    "publisherName": "温木"</span><br><span class="line">  &#125;,</span><br><span class="line">  "nsis": &#123;</span><br><span class="line">    "allowToChangeInstallationDirectory": true,</span><br><span class="line">    "oneClick": false,</span><br><span class="line">    "perMachine": false</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>增加打包前执行 build</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"predist":"npm run build"</span><br></pre></td></tr></table></figure>

<p>打包</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run dist</span><br></pre></td></tr></table></figure>

<p>这就会根据你的环境生成对应的包，比如你是 mac 则生成 mac 对应的安装包。</p>
<h2 id="优化安装包"><a href="#优化安装包" class="headerlink" title="优化安装包"></a>优化安装包</h2><p>上面虽然成功生成了安装包，但是体积比较大，通过生成的文件我们知道，主要有两个文件我们可以优化，一个是 app.asar,一个是 electron.asar，app.asar 中是我们业务程序的代码，electron.asar 是系统的，我们没法改变。<br>那能优化就是 app.asar.它包含的内容如下：</p>
<p>.<br>├── build<br>├── main.js<br>├── menuTemplate.js<br>├── node_modules<br>├── package.json<br>├── settings<br>└── src</p>
<blockquote>
<p>asar extract app.asar tmp_app<br>使用上面的命令，把 app.asar 中的内容“解压”到 tmp_app 文件夹中<br>使用<code>tree -L 1</code>查看目录结构</p>
</blockquote>
<p>我们知道<code>node_modules</code>中<code>react</code>使用到的安装包，其实已经打包到了<code>build</code>文件夹中，是不需要再进行打包的。<br>由于<code>electron-build</code>不会对开发依赖项进行打包，因此可以把不需要打包的依赖项移动到开发依赖项中(开发过程中可能不能这么干，只能在打包的时候这么做)。</p>
<p>优化打包文件引入</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">"files": [</span><br><span class="line">  "build/**/*",</span><br><span class="line">  "node_modules/**/*",</span><br><span class="line">  "settings/**/*",</span><br><span class="line">  "package.json",</span><br><span class="line">  "main.js",</span><br><span class="line">  "./menuTemplate.js",</span><br><span class="line">  "./src/AppWindow.js",</span><br><span class="line">  <span class="string">"./src/utils/QiNiuManager.js"</span></span><br><span class="line">],</span><br></pre></td></tr></table></figure>

<p>现在配置了很多个打包文件，其实需要引入的就两类文件，一个是前端的，一个是 electron 的。前端的都已打包到 build 文件夹中。<br>而 electron 的 js 代码我们是一个一个单独引用的。我们也可以把他们打包到一起，这样就可以只引入一个文件了。</p>
<p>1.新建一个 webpack 的配置文件 webpack.config.js<br>webpack.config.js 是 webpack 的默认配置文件，因为前端是通过编写的代码进行打包的，所以并没有使用到这个配置文件，所以我们新建一个也不会对前端打包造成影响。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">"path"</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  target: <span class="string">"electron-main"</span>,</span><br><span class="line">  entry: <span class="string">"./main.js"</span>,</span><br><span class="line">  output: &#123;</span><br><span class="line">    path: path.resolve(__dirname, <span class="string">"./build"</span>),</span><br><span class="line">    filename: <span class="string">"main.js"</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">  node: &#123;</span><br><span class="line">    __dirname: <span class="literal">false</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>注意：</p>
<ol>
<li>配置 target 为<code>electron-main</code></li>
<li>配置 node 设置<strong>dirname，教程说是</strong>dirname 默认返回一个斜杠，但我测试返回没问题，加不加这个配置都一样。</li>
</ol>
<p>增加 build 的命令</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"buildElectron": "webpack",</span><br></pre></td></tr></table></figure>

<h3 id="electron-代码打包到一起后需要修改的地方"><a href="#electron-代码打包到一起后需要修改的地方" class="headerlink" title="electron 代码打包到一起后需要修改的地方"></a>electron 代码打包到一起后需要修改的地方</h3><ol>
<li><p>package.json 中的 build 的 files<br>这是只需要设置打包后的 main.js 文件即可，但已配置了 build 目录，所以把 electron 的代码引用都删除即可。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">"files": [</span><br><span class="line">  "build/**/*",</span><br><span class="line">  "node_modules/**/*",</span><br><span class="line">  "settings/**/*",</span><br><span class="line">  <span class="string">"package.json"</span></span><br><span class="line">],</span><br></pre></td></tr></table></figure></li>
<li><p>electron 的入口文件<br>electron 默认读取的是 package.json 的 main 字段配置的文件，打包读取的也是这个，但是现在打包需要读取 build 中的 main.js，所以增加 build 的配置</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">"extraMetadata": &#123;</span><br><span class="line">  "main": "./build/main.js"</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>

<p>这样打包的时候就会读取这里指定的文件。</p>
</li>
<li><p>修改 npm 的钩子</p>
</li>
</ol>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">"prepack": "npm run build &amp;&amp; npm run buildElectron",</span><br><span class="line">"predist": "npm run build &amp;&amp; npm run buildElectron"</span><br></pre></td></tr></table></figure>

<ol start="4">
<li>修改 main.js 文件<br>因为生产环境 main.js 的路径和前端页面在同一个文件夹下，所以引用路径也发生改变</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> urlLocation = isDev ? <span class="string">"http://localhost:3000/"</span> : <span class="string">`file://<span class="subst">$&#123;join(__dirname, <span class="string">"./index.html"</span>)&#125;</span>`</span>;</span><br></pre></td></tr></table></figure>

<ol start="5">
<li>把生产环境依赖项移动到开发依赖项中</li>
</ol>
<h2 id="自动更新"><a href="#自动更新" class="headerlink" title="自动更新"></a>自动更新</h2><p>自动更新就是当每次打开软件时，会和远程存储下载资源的版本进行对比，如果有新版本，就提示自动更新。<br>既然要自动更新，那首先设置资源存储的地方并自动发布。electron-builder 提供了自动发布的功能，并且支持很多平台，其中我们喜欢的 GitHub 就在之列。具体详情可在官网的<a href="https://www.electron.build/configuration/publish" target="_blank" rel="noopener">Publish</a>模块查看。</p>
<h3 id="自动发布"><a href="#自动发布" class="headerlink" title="自动发布"></a>自动发布</h3><ol>
<li>指定发布使用的平台<br>在<code>electron-builder</code>的配置项中增加<code>publish</code>配置。由官网可看出，<code>publish</code>的值可以是<code>String | Object | Array&lt;Object | String&gt;</code>，其实如果设置了 GitHub 的 token(GH_TOKEN)，默认使用的就是 GitHub 平台。可以同时指定多个平台。<br>在 package.json 中增加<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"build"</span>:&#123;</span><br><span class="line">     <span class="string">"publish"</span>: [<span class="string">"github"</span>, <span class="string">"bintray"</span>],</span><br><span class="line">     <span class="comment">// 或者如下</span></span><br><span class="line">     <span class="string">"publish"</span>: [&#123;<span class="attr">provider</span>: <span class="string">"github"</span>&#125;, &#123;<span class="attr">provider</span>: <span class="string">"bintray"</span>&#125;]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li>配置发布命令<br>GitHub 的下载资源都在 release 模块，<code>electron-builder</code>提供了往 GitHub 的 release 模块推送静态资源的方式。<br>官网给出了，使用<code>npm script</code>只需要增加<code>release</code>命令即可。这样每次生成安装包后，自动发布到 GitHub 上的 release。</li>
</ol>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">"scripts": &#123;</span><br><span class="line">  ......</span><br><span class="line">  "release": "electron-builder",</span><br><span class="line">  "prerelease": "npm run build &amp;&amp; npm run buildElectron"</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>

<p>上面配置完，还需要 github 的 token，不然 push 不上去。<a href="https://github.com/settings/tokens" target="_blank" rel="noopener">获取 token 的地址</a><br>点击头像-&gt;设置-&gt;Developer settings-&gt;Personal access tokens<br>然后生成一个 <code>token</code> 传给 <code>electron-builder</code> 即可</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"release"</span>: <span class="string">"cross-env GH_TOKEN=d728e4bd5fefe3ba74881c0171284b85bb95cd6d electron-builder"</span>,</span><br></pre></td></tr></table></figure>

<p>到目前为止，所有的配置就完成了。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run release</span><br></pre></td></tr></table></figure>

<p>执行后，不仅重新生成了安装包，并且上传到了 GitHub 上，在项目的 release 模块可看到，生成的安装包文件都被上传了。<br>这时，上传的文件还是 draft 状态，也就是草稿状态，可以点击编辑，编写一些描述，然后点击发布，这时就成了发布状态；也可以点击保存成 draft。</p>
<h3 id="自动更新-1"><a href="#自动更新-1" class="headerlink" title="自动更新"></a>自动更新</h3><p>electron 本身也提供了程序更新的方式，但是官网也说了，如果使用 electron-builder 进行打包，可以使用 electron-updater 模块，它不依赖任何服务器并且可以从 S3, GitHub 或者任何其它静态文件存储更新. 这避开了 Electron 内置的更新机制，</p>
<p>安装 electron-updater</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i electron-udpater --save-dev</span><br></pre></td></tr></table></figure>

<p>然后在主进程中添加检查更新的代码，重新打包，然后点击生成的安装后文件中的程序，就可以看到效果。注意 GitHub 上的项目需要设置成公共的，私有的是获取不到的。</p>
<h3 id="开发模式下测试自动更新"><a href="#开发模式下测试自动更新" class="headerlink" title="开发模式下测试自动更新"></a>开发模式下测试自动更新</h3><p>上面的配置都是在开发完后，打包成功后，点击安装包，然后查看效果，比较费劲，出了问题还的盲改后，再打包来看效果，效率比较低。<br>如果能在开发过程中就查看效果，那就很方便了。<br>上面说过，查看打包后自动更新，需要使用 release 命令，使用 dist 是会报错的，因为更新需要一个叫 app-update.yml 的文件告诉它一些更新需要的信息，比如用户名，仓库名等等。。<br>开发模式下，我们可以手动创建这个文件，名字前加上 dev，叫<code>dev-app-update.yml</code></p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">owner:</span> <span class="string">codepandy</span></span><br><span class="line"><span class="attr">repo:</span> <span class="string">electron_react_markdown</span></span><br><span class="line"><span class="attr">provider:</span> <span class="string">github</span></span><br><span class="line"><span class="attr">updaterCacheDirName:</span> <span class="string">electron-react-markdown-updater</span></span><br></pre></td></tr></table></figure>

<p>上面内容是从正式生成的<code>app-update.yml</code>中 copy 的，最后一个可以不要。<br>然后在程序中判断，如果是开发模式，就使用我们创建的<code>dev-app-update.yml</code>配置文件。</p>
</div></article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">wenmu</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="http://blog.wangpengpeng.site/2020/01/09/electron+react+%E4%B8%83%E7%89%9B%E4%BA%91%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/">http://blog.wangpengpeng.site/2020/01/09/electron+react+%E4%B8%83%E7%89%9B%E4%BA%91%E5%BC%80%E5%8F%91%E7%AC%94%E8%AE%B0/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank" rel="noopener">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="http://blog.wangpengpeng.site">温木的博客</a>！</span></div></div><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/electron/">electron</a><a class="post-meta__tags" href="/tags/React/">React</a></div><div class="post-qr-code"><div class="post-qr-code-item"><img class="post-qr-code__img" src="https://i.loli.net/2020/02/27/hOBzIxFDJMCrmtN.jpg"><div class="post-qr-code__desc">微信打赏</div></div></div><nav id="pagination"><div class="prev-post pull-left"><a href="/2020/01/09/flex%E6%8D%A2%E8%A1%8C%E6%97%B6%E5%85%83%E7%B4%A0%E6%B2%A1%E6%9C%89%E6%8C%A8%E7%9D%80%E4%B8%8A%E4%B8%80%E8%A1%8C%E6%98%BE%E7%A4%BA/"><i class="fa fa-chevron-left">  </i><span>flex换行时元素没有挨着上一行显示</span></a></div><div class="next-post pull-right"><a href="/2020/01/09/javascript%E5%8E%9F%E5%9E%8B%E9%93%BE%E5%AE%B9%E6%98%93%E6%B7%B7%E6%B7%86%E7%9A%84%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86/"><span>javascript原型链容易混淆的相关知识</span><i class="fa fa-chevron-right"></i></a></div></nav><div id="vcomment"></div><script src="https://cdn1.lncld.net/static/js/3.0.4/av-min.js"></script><script src="https://cdn.jsdelivr.net/npm/valine/dist/Valine.min.js"></script><script>var notify = 'false' == true ? true : false;
var verify = 'false' == true ? true : false;
var GUEST_INFO = ['nick','mail','link'];
var guest_info = 'nick,mail,link'.split(',').filter(function(item){
  return GUEST_INFO.indexOf(item) > -1
});
guest_info = guest_info.length == 0 ? GUEST_INFO :guest_info;
window.valine = new Valine({
  el:'#vcomment',
  notify:notify,
  verify:verify,
  appId:'U1QqpeQNuBnRsfygHk1GQ30q-gzGzoHsz',
  appKey:'dunDQzEseDzgsKgw4qLQcog1',
  placeholder:'支持markdown！',
  avatar:'wavatar',
  guest_info:guest_info,
  pageSize:'20',
  lang: 'zh-cn'
})</script></div></div><footer><div class="layout" id="footer"><div class="copyright">&copy;2019 - 2020 By wenmu</div><div class="framework-info"><span>驱动 - </span><a href="http://hexo.io" target="_blank" rel="noopener"><span>Hexo</span></a><span class="footer-separator">|</span><span>主题 - </span><a href="https://github.com/Molunerfinn/hexo-theme-melody" target="_blank" rel="noopener"><span>Melody</span></a></div><div class="busuanzi"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span id="busuanzi_container_page_pv">该文访问量<span id="busuanzi_value_page_pv"></span><span></span></span></div></div></footer><i class="fa fa-arrow-up" id="go-up" aria-hidden="true"></i><script src="https://cdn.jsdelivr.net/npm/animejs@latest/anime.min.js"></script><script src="https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-animate@latest/velocity.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-ui-pack@latest/velocity.ui.min.js"></script><script src="/js/utils.js?version=1.6.1"></script><script src="/js/fancybox.js?version=1.6.1"></script><script src="/js/sidebar.js?version=1.6.1"></script><script src="/js/copy.js?version=1.6.1"></script><script src="/js/fireworks.js?version=1.6.1"></script><script src="/js/transition.js?version=1.6.1"></script><script src="/js/scroll.js?version=1.6.1"></script><script src="/js/head.js?version=1.6.1"></script><script>if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
  $('#nav').addClass('is-mobile')
  $('footer').addClass('is-mobile')
}</script></body></html>